package com.me.myFramework.myAop.aop200;

import com.me.myFramework.myAop.IBuy;
import com.me.myFramework.myAop.Switch;
import com.me.myFramework.myAop.aop200.advice.method.AfterReturningAdvice;
import com.me.myFramework.myAop.aop200.advice.method.MethodBeforeAdvice;
import org.springframework.aop.Pointcut;

import java.lang.reflect.Method;

/**
 * 自己实现 AOP-200  <p></p>
 *
 * 优化多切面的实现方式，一个代理类中借助责任链 链式执行 advice
 *
 * @author ME
 * @date 2021/9/26
 */
public class MyAop200 {

    /**
     * 通过 模板模式 提取增强逻辑：方法执行前、正常返回、异常返回
     */
    public static void main(String[] args) throws Throwable {
        ProxyFactory factory = new ProxyFactory(new Switch());
        factory.addAdvisor(new DefaultPointcutAdvisor(new BeforeAdvice111(), Pointcut.TRUE));
        factory.addAdvisor(new DefaultPointcutAdvisor(new AfterReturningAdvice222(), Pointcut.TRUE));
        IBuy proxy = (IBuy) factory.getProxy();
        proxy.buy("Jack");
    }

    /**
     * 方法前的增强111
     */
    static class BeforeAdvice111 implements MethodBeforeAdvice {
        @Override
        public void before(Method method, Object[] args, Object target) throws Throwable {
            if (isCustomMethod(method.getName())) {
                System.out.println("[AOP1] 就是想记录谁消费了：" + args[0]);
            }
        }
    }

    /**
     * 方法正常返回的增强222
     */
    static class AfterReturningAdvice222 implements AfterReturningAdvice {
        @Override
        public void afterReturning(Object returnValue, Method method, Object[] args, Object target) {
            if (isCustomMethod(method.getName())) {
                if ("Xbox".equals(returnValue)) {
                    System.out.println("[AOP2] 没货了，没买到 Xbox");
                }
                else {
                    System.out.println("[AOP2] 喜提一台 " + returnValue);
                }
            }
        }
    }

    static boolean isCustomMethod(String methodName) {
        return !"toString".equals(methodName) && !"hashCode".equals(methodName) && !"equals".equals(methodName)
                && !"clone".equals(methodName);
    }

}
